/* A table mapping each PFN to its new MFN. */
static unsigned long *pfn_to_mfn_table;
+/* This may allow us to create a 'quiet' command-line option, if necessary. */
+#define verbose_printf(_f, _a...) \
+ do { \
+ printf( _f , ## _a ); \
+ fflush(stdout); \
+ } while ( 0 )
+
static int get_pfn_list(
int domain_id, unsigned long *pfn_buf, unsigned long max_pfns)
{
dom0_op_t op;
int rc = 1, i, j;
unsigned long mfn, pfn, dom = 0;
+ unsigned int prev_pc, this_pc;
/* Number of page frames in use by this XenoLinux session. */
unsigned long nr_pfns;
goto out;
}
+ verbose_printf("Reloading memory pages: 0%%");
+
/*
* Now simply read each saved frame into its new machine frame.
* We uncanonicalise page tables as we go.
*/
+ prev_pc = 0;
for ( i = 0; i < nr_pfns; i++ )
{
+ this_pc = (i * 100) / nr_pfns;
+ if ( (this_pc - prev_pc) >= 5 )
+ {
+ verbose_printf("\b\b\b\b%3d%%", this_pc);
+ prev_pc = this_pc;
+ }
+
mfn = pfn_to_mfn_table[i];
if ( !checked_read(fd, page, PAGE_SIZE) )
if ( flush_mmu_updates() )
goto out;
+ verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
+
/* Uncanonicalise the suspend-record frame number and poke resume rec. */
pfn = ctxt.i386_ctxt.esi;
if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
rc = do_dom0_op(&op);
out:
- /* If we experience an error then kill the half-constructed domain. */
- if ( (rc != 0) && (dom != 0) )
+ if ( rc != 0 )
+ {
+ if ( dom != 0 )
+ {
+ op.cmd = DOM0_DESTROYDOMAIN;
+ op.u.destroydomain.domain = dom;
+ op.u.destroydomain.force = 1;
+ (void)do_dom0_op(&op);
+ }
+ }
+ else
{
- op.cmd = DOM0_DESTROYDOMAIN;
- op.u.destroydomain.domain = dom;
- op.u.destroydomain.force = 1;
- (void)do_dom0_op(&op);
+ /* Success: print the domain id. */
+ printf("DOM=%ld\n", dom);
}
return !!rc;
/* A table mapping each current MFN to its canonical PFN. */
static unsigned long *mfn_to_pfn_table;
+/* This may allow us to create a 'quiet' command-line option, if necessary. */
+#define verbose_printf(_f, _a...) \
+ do { \
+ printf( _f , ## _a ); \
+ fflush(stdout); \
+ } while ( 0 )
+
static int devmem_fd;
static int init_pfn_mapper(void)
dom0_op_t op;
int rc = 1, i, j;
unsigned long mfn, dom;
+ unsigned int prev_pc, this_pc;
/* Remember if we stopped the guest, so we can restart it on exit. */
int we_stopped_it = 0;
}
unmap_pfn(ppage);
+ verbose_printf("Saving memory pages: 0%%");
+
/* Now write out each data page, canonicalising page tables as we go... */
+ prev_pc = 0;
for ( i = 0; i < srec.nr_pfns; i++ )
{
+ this_pc = (i * 100) / srec.nr_pfns;
+ if ( (this_pc - prev_pc) >= 5 )
+ {
+ verbose_printf("\b\b\b\b%3d%%", this_pc);
+ prev_pc = this_pc;
+ }
+
mfn = pfn_to_mfn_table[i];
ppage = map_pfn(mfn);
}
}
+ verbose_printf("\b\b\b\b100%%\nMemory saved.\n");
+
/* Success! */
rc = 0;
#include <asm/uaccess.h>
#include <asm/domain_page.h>
-#if 1
+#if 0
#define MEM_LOG(_f, _a...) printk("DOM%d: (file=memory.c, line=%d) " _f "\n", current->domain, __LINE__, ## _a )
#else
#define MEM_LOG(_f, _a...) ((void)0)
static int get_l2_table(unsigned long page_nr)
{
+ struct pfn_info *page;
+ struct task_struct *p;
l2_pgentry_t *p_l2_entry, l2_entry;
int i, ret=0;
memcpy(p_l2_entry,
&idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t));
- p_l2_entry[(PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT) -
- DOMAIN_ENTRIES_PER_L2_PAGETABLE] =
- mk_l2_pgentry(__pa(current->mm.perdomain_pt) | __PAGE_HYPERVISOR);
p_l2_entry[(LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT) -
DOMAIN_ENTRIES_PER_L2_PAGETABLE] =
mk_l2_pgentry((page_nr << PAGE_SHIFT) | __PAGE_HYPERVISOR);
+ /*
+ * The per-domain PGD is slightly tricky, as we may not be executing
+ * in the context of the correct domain (DOM0 builds pt's for others).
+ */
+ page = frame_table + page_nr;
+ if ( (p = find_domain_by_id(page->flags & PG_domain_mask)) != NULL )
+ {
+ p_l2_entry[(PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT) -
+ DOMAIN_ENTRIES_PER_L2_PAGETABLE] =
+ mk_l2_pgentry(__pa(p->mm.perdomain_pt) | __PAGE_HYPERVISOR);
+ put_task_struct(p);
+ }
+
out:
unmap_domain_mem(p_l2_entry);
return ret;